#if !defined(AFX_JJSKELETON_H)
#define AFX_JJSKELETON_H

#include "maskvolume.h"


#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

typedef	struct HeapNodeInformation {
	float				time;
	short				x;
	short				y;
	short				z;
	unsigned short		pointer;
} Node;

#include "maskvolume.h"
#include "JJConnectedComponent.h"

#include <vector>


class ConnectedComponent;

class Skeleton
{
private:
	ConnectedComponent	m_ConnectedComponent;
	float*					m_pLongDistanceMap;
	float*					m_pDistanceMapFromPS;
	float*					m_pDistanceMapFromPS_FAST_WAVE;

	unsigned char*			m_pPointType;
	unsigned short*			m_pClusterGraph;
	unsigned short			m_nClusterMapping[65535];
	Node					m_ExtremePoint[65535];

	unsigned int*			pTable;

	RxMaskVolume*			m_pVesselVolume;
	RxMaskVolume*			m_pVesselEdge;
	RxMaskVolume*			m_pSkeleton;
	RxMaskVolume*			m_pCP;

	Node					m_arrHeap[1000000];
	unsigned long			m_lHeapLength;
	
	float					m_fVel;
	float					m_fMaxDistanceMapFromPS;

	short					m_PS_X;
	short					m_PS_Y;
	short					m_PS_Z;

	unsigned short			m_nClusterIndex;
	unsigned short			m_GraphLink[65535][20];		// parent and his sons
	unsigned short			m_GL_Index[65535];			// how many sons for a node

	unsigned short*			m_pLabel;
	unsigned short			m_nObjectID[1000];
	unsigned short			m_nObjectNum;

	bool					m_biggestBranchOnly;

public:
	short					m_VolX;
	short					m_VolY;
	short					m_VolZ;
	short					m_OffsetX;
	short					m_OffsetY;
	short					m_OffsetZ;

	Node					m_ControlPoint[30000];
	Node					m_BranchPoint[30000];

	unsigned long			m_nExtremeNum;
	unsigned long			m_nBranchNum;

private:
	void HeapInitialization(void);
	Node HeapRemoveMin(void);
	void HeapInsert(Node NewNode);
	void HeapModify(Node NewNode);
	bool HeapSearch(Node SearchNode);
	bool HeapEmpty(void);

	void PrintDistanceMap2VTK(short nDistanceMapMode);
	void PrintDistanceMap(short nMode, short nDistanceMapMode);

	void Iteration_ORD_1(short nDistanceMapMode);
	float solve_ORD_1(int i1, int j1, int k1, int i2, int j2, int k2, int i3, int j3, int k3, float sol, short nDistanceMapMode);

	void FindPointSource(short nObjectLabel);
	void PropagateFromPS(short nObjectLabel);
	void PropagateFromPS_FAST_WAVE(short nObjectLabel);
	void BuildClusterGraph(void);
	void ExtractCenterline(void);

	void BuildCGLink(unsigned short nParent, unsigned short nChild);
	void SetNode(short nSeed_X, short nSeed_Y, short nSeed_Z, unsigned short nDistance, unsigned short nClusterIndex);

	void Evaluation(void);
	void VisualizeSkeleton(void);

	inline float minimum(float num1, float num2);

	//void ControlProgress(RxProgressWnd *pProWnd);
public:
	Skeleton();
	~Skeleton();

	void Initialization(void);
	void SetParameter(RxMaskVolume* pVesselEdge, RxMaskVolume* pVesselVolume, RxMaskVolume* pSkeleton, RxMaskVolume* pCP, int minX, int maxX, int minY, int maxY, int minZ, int maxZ, bool bRef);
	void SetBiggestBranch(bool flag) { m_biggestBranchOnly=flag;}
	void Skeletonization(void);

	int FindConnectedComponent(void);

	double GetWallWeight(int i, int j, int k);
	double GetPSWeight(int i, int j, int k);
	double GetDistanceMapValue(int i, int j, int k);
	float GetDistFromWall(int i, int j, int k);
	int GetBranchPoints(std::vector<Node> &vec);
	int GetBranchAndExtremePoints(std::vector<Node> &vec);
	
	float* GetDistanceMapFromPS();
};

#endif